package externalSort.Tournament;

import java.io.*;
import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class readingTask implements Runnable {
    private final BufferedReader br;
    private boolean allFinished;
    private List<bufferSimulator> buffers;

    private Lock bufferLock;
    private Lock lock;
    private Semaphore toActive;
    private Semaphore toReading;

    private int cntOfReading;

    public readingTask(BufferedReader br,
                       Lock bufferLock, Semaphore toActive, Semaphore toReading,
                       List<bufferSimulator> buffers){
//        System.out.println("=== [readingTask] 初始化开始 ===");
        this.br=br;
        this.buffers=buffers;
        this.lock=new ReentrantLock();
        this.bufferLock=bufferLock;

        this.toReading=toReading;
        this.toActive=toActive;

        this.allFinished=false;
        this.cntOfReading=0;
//        System.out.println("=== [readingTask] 初始化完成 ===");
    }

    @Override
    public void run(){
//        System.out.println("=== [readingTask] 读取线程开始运行 ===");
        try{
//            int readCycle = 0;
            while(!isAllFinished()){
//                readCycle++;
//                System.out.println("[read] 循环 " + readCycle + " - 尝试获取toReading, 当前可用: " + toReading.availablePermits());
                toReading.acquire();
//                System.out.println("[read] 成功获取toReading");

                bufferLock.lock();
//                System.out.println("[read] 获取bufferLock，检查缓冲区状态:");

                bufferSimulator cur=null;
                for(bufferSimulator buffer:buffers){
//                    System.out.println("[read] 缓冲区状态: " + buffer.getState() + "，大小: " + buffer.size());
                    if(buffer.getState()==BufferState.IDLE){
                        cur=buffer;
//                        System.out.println("[read] 找到IDLE缓冲区，大小: " + cur.size());
                        break;
                    }
                }
//                System.out.print("\n");

                if (cur != null) {
//                    System.out.println("[read] 设置缓冲区状态为READING");
                    cur.setState(BufferState.READING);
                    bufferLock.unlock();
//                    System.out.println("[read] 释放bufferLock，准备填充缓冲区");
//
                    boolean ret=fillBuffer(cur);
//                    System.out.println("[read] fillBuffer返回: " + ret);

                    bufferLock.lock();
//                    System.out.println("[read] 获取bufferLock，设置缓冲区状态为ACTIVE");
                    cur.setState(BufferState.ACTIVE);

//                    System.out.println("[read] 释放toActive，当前可用: " + toActive.availablePermits());
                    toActive.release();

                    this.lock.lock();
                    cntOfReading++;
                    this.lock.unlock();

                    bufferLock.unlock();
//                    System.out.println("[read] 释放bufferLock");

                    if(!ret){
//                        System.out.println("[read] fillBuffer返回false，准备关闭读取器");
                        shut();
                    }
                }else{
//                    System.out.println("(Error)[readingTask]: 未从list中找出IDLE的buffer");
                    bufferLock.unlock();
                }

//                System.out.println("[read] 当前allFinished=" + isAllFinished());
            }
//            System.out.println("=== [readingTask] 读取线程运行结束 ===");
        }
        catch (Exception e) {
//            System.out.println("(ERROR)[readingTask] 发生异常: " + e.getMessage());
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    private boolean fillBuffer(bufferSimulator buffer) {
//        System.out.println("[fillBuffer] 开始填充缓冲区，当前缓冲区大小: " + buffer.size() + "/" + buffer.capacity);
        String s = null;
//        int readCount = 0;
        try {
            // 先检查buffer是否已满，如果已满则直接返回
            if (buffer.isFull()) {
                System.out.println("(INFO) [fillBuffer] buffer已满，无需读取");
                return true;
            }

            // 读取数据直到buffer满或文件结束
            while (!buffer.isFull() && (s = this.br.readLine()) != null) {
                int curNum = Integer.parseInt(s.trim());
//                readCount++;
//
//                if (readCount % 10 == 0) { // 每10个值打印一次进度
//                    System.out.println("[fillBuffer] 读取第 " + readCount + " 个值: " + curNum);
//                } else {
//                    System.out.println("[fillBuffer] 读取值: " + curNum);
//                }

                boolean ret = buffer.add(curNum);

                // 正常情况下，buffer未满时add应该总是成功
                if (!ret) {
                    System.out.println("(WARN) [fillBuffer] 意外的添加失败，buffer状态异常");
                    break;
                }
            }

            boolean fileEnded = (s == null);
//            System.out.println("[fillBuffer] 填充完成，共读取 " + readCount + " 个值，缓冲区大小: " + buffer.size() +
//                    "/" + buffer.capacity + "，文件结束: " + fileEnded);

            return !fileEnded;

        } catch (IOException e) {
//            System.out.println("[externalSort.Tournament.readingTask]:IOExpectation occur "+ e.getMessage());
            return false;
        } catch (NumberFormatException e) {
            System.out.println("(ERROR)[fillBuffer] 数字格式错误: " + e.getMessage());
            return false;
        }
    }

    public boolean isAllFinished() {
        lock.lock();
        try {
            boolean result = this.allFinished;
//            System.out.println("[isAllFinished] 检查完成状态: " + result);
            return result;
        } finally {
            lock.unlock();
        }
    }

    private void shut() throws IOException {
        this.lock.lock();
//        System.out.println("=== [shut] 开始关闭读取器 ===");
        this.br.close();
        allFinished = true;
//        System.out.println("=== [shut] 读取器已关闭，allFinished设置为true ===");
        this.lock.unlock();
    }

    public int getCnt(){
        try{
            lock.lock();
            return cntOfReading;
        }finally {
            lock.unlock();
        }
    }
}